﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Windows.Markup;
using SilverTile.Xaml;
using SilverTile;
using System.Linq;
using SilverTile.Sprites;
using SilverTile.Viewports;

namespace SilverTileTests
{

    [TestClass]
    public class XamlGameAreaTests
    {

        private string _xaml =
            @"
            <UserControl
                xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
                xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""
                         xmlns:st=""clr-namespace:SilverTile.Xaml;assembly=SilverTile"">

                <UserControl.Resources>
                    <st:SpriteFrame x:Key=""Sand"" Source=""/SilverTileTests;component/Tiles/0002.png"" />    

                    <st:GameAreaGrid x:Key=""Map1"" AreaName=""Area1"" Rows=""3"" Columns=""2"" TileWidth=""32"" TileHeight=""16"">
                        <st:SpriteTile X=""0""  Y=""0"" Blocking=""True"" Frame=""{StaticResource Sand}"" />
                        <st:SpriteTile X=""0""  Y=""1"" Blocking=""False"" Frame=""{StaticResource Sand}"" />
                        <st:SpriteTile X=""0""  Y=""2"" Blocking=""False"" Frame=""{StaticResource Sand}"" />
                        <st:SpriteTile X=""1""  Y=""0"" Blocking=""False"" Frame=""{StaticResource Sand}"" />
                        <st:SpriteTile X=""1""  Y=""1"" Blocking=""False"" Frame=""{StaticResource Sand}"" />
                        <st:SpriteTile X=""1""  Y=""2"" Blocking=""False"" Frame=""{StaticResource Sand}"" />
                    </st:GameAreaGrid>

                </UserControl.Resources>

            </UserControl>
            ";

        [TestMethod]
        public void Xaml_Fragment_Should_Be_Parseable()
        {

            UserControl xamlUc = (UserControl)XamlReader.Load(_xaml);

            Assert.IsNotNull(xamlUc, "Xaml was not deserialized properly");

            object mapDefResource = xamlUc.Resources["Map1"];
            Assert.IsNotNull(mapDefResource, "Map1 resource was not defined");
            Assert.IsInstanceOfType(mapDefResource, typeof(GameAreaGrid), "GameArea definintion was deserialized to the wrong type");
                        
        }

        [TestMethod]
        public void Xaml_Fragment_Should_Be_Parsed_Correctly()
        {

            UserControl xamlUc = (UserControl)XamlReader.Load(_xaml);
            GameAreaGrid gameArea = (GameAreaGrid)xamlUc.Resources["Map1"];

            Assert.AreEqual(6, gameArea.BackgroundSprites.Count, "Incorrect number of background sprites defined");
            Assert.AreEqual(3, gameArea.Rows, "Incorrect value for Rows");
            Assert.AreEqual(2, gameArea.Columns, "Incorrect value for Columns");
            Assert.AreEqual(32, gameArea.TileWidth, "Incorrect value for TileWidth");
            Assert.AreEqual(16, gameArea.TileHeight, "Incorrect value for TileHeight");
            Assert.AreEqual("Area1", gameArea.AreaName, "Incorrect value for AreaName");

        }

        [TestMethod]
        public void Parsed_Xaml_Should_Be_Assignable_To_Viewport()
        {

            UserControl xamlUc = (UserControl)XamlReader.Load(_xaml);
            GameAreaGrid gameArea = (GameAreaGrid)xamlUc.Resources["Map1"];

            IViewport viewport = new Viewport(100, 100);
            viewport.SetGameArea(gameArea);

            Assert.AreEqual(gameArea.BackgroundSprites.Count, viewport.BackgroundSprites.Count(), "Incorrect number of background sprites read");

            // Ensure all sprites are at the right place
            foreach (SpriteTile tile in gameArea.BackgroundSprites)
            {

                ISprite sprite = viewport.BackgroundSprites.Where(s => s.X.Equals(tile.X * gameArea.TileWidth) && s.Y.Equals(tile.Y * gameArea.TileHeight)).FirstOrDefault();

                Assert.IsNotNull(sprite, "Did not find a sprite at location (" + tile.X + "," + tile.Y + ")");
                Assert.AreEqual(tile.Blocking, sprite.Blocking, "Blocking was not set correctly");
                
            }

        }

        [TestMethod]
        public void Blocking_Property_Should_Be_Set_Correctly()
        {
            UserControl xamlUc = (UserControl)XamlReader.Load(_xaml);
            GameAreaGrid gameArea = (GameAreaGrid)xamlUc.Resources["Map1"];

            IViewport viewport = new Viewport(100, 100);
            viewport.SetGameArea(gameArea);

            ISprite bgSprite = viewport.BackgroundSprites.First();

            Assert.IsTrue(bgSprite.Blocking, "Blocking should be true");

            ISprite bgSprite2 = viewport.BackgroundSprites.Skip(1).First();
            Assert.IsFalse(bgSprite2.Blocking, "Blocking should be false");
        
        }

        [TestMethod]
        public void GameArea_With_All_Cells_Occupied_Should_Return_Valid_True()
        {

            GameAreaGrid gameArea = new GameAreaGrid
            {
                Columns = 2,
                Rows = 2,
                TileHeight = 1,
                TileWidth = 1
            };

            gameArea.BackgroundSprites.Add(new SpriteTile { X = 0, Y = 0 });
            gameArea.BackgroundSprites.Add(new SpriteTile { X = 1, Y = 0 });
            gameArea.BackgroundSprites.Add(new SpriteTile { X = 0, Y = 1 });
            gameArea.BackgroundSprites.Add(new SpriteTile { X = 1, Y = 1 });

            Assert.IsTrue(gameArea.Validate(), "GameArea.Validate did not return true");

        }

        [TestMethod]
        public void GameArea_With_Some_Cells_Unoccupied_Should_Return_Valid_False()
        {

            GameAreaGrid gameArea = new GameAreaGrid
            {
                Columns = 2,
                Rows = 2,
                TileHeight = 1,
                TileWidth = 1
            };

            gameArea.BackgroundSprites.Add(new SpriteTile { X = 0, Y = 0 });
            //gameArea.BackgroundSprites.Add(new SpriteTile { X = 1, Y = 0 });
            gameArea.BackgroundSprites.Add(new SpriteTile { X = 0, Y = 1 });
            gameArea.BackgroundSprites.Add(new SpriteTile { X = 1, Y = 1 });

            Assert.IsFalse(gameArea.Validate(), "GameArea.Validate did not return false");

        }

        [TestMethod]
        public void GameArea_With_Some_Cells_Occupied_Twice_Should_Return_Valid_False()
        {

            GameAreaGrid gameArea = new GameAreaGrid
            {
                Columns = 2,
                Rows = 2,
                TileHeight = 1,
                TileWidth = 1
            };

            gameArea.BackgroundSprites.Add(new SpriteTile { X = 0, Y = 0 });
            gameArea.BackgroundSprites.Add(new SpriteTile { X = 1, Y = 0 });
            gameArea.BackgroundSprites.Add(new SpriteTile { X = 0, Y = 1 });
            gameArea.BackgroundSprites.Add(new SpriteTile { X = 1, Y = 1 });

            gameArea.BackgroundSprites.Add(new SpriteTile { X = 1, Y = 0 });

            Assert.IsFalse(gameArea.Validate(), "GameArea.Validate did not return false");

        }
              
    }
}
